package com.duobaoyu.dby.supply.db.repository.message.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.duobaoyu.dby.common.core.constant.CommonConstants;
import com.duobaoyu.dby.supply.db.constant.SupplyMapperConstant;
import com.duobaoyu.dby.supply.db.entity.message.ChannelMessage;
import com.duobaoyu.dby.supply.db.entity.message.ChannelMessageOrder;
import com.duobaoyu.dby.supply.db.entity.message.ChannelMessageProduct;
import com.duobaoyu.dby.supply.db.helper.DynamicTableNameHelper;
import com.duobaoyu.dby.supply.db.repository.message.ChannelMessageRepository;
import com.duobaoyu.dby.supply.db.util.OperateAuthUtil;
import com.mongodb.client.result.UpdateResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author liyang
 * @version 1.0.0
 * @ClassName ChannelMessageServiceImpl
 * @createTime 16:24:00 2023/09/27
 */
@Slf4j
@Repository
@RequiredArgsConstructor
public class ChannelMessageRepositoryImpl implements ChannelMessageRepository {

	private final MongoTemplate mongoTemplate;

	@Override
	public boolean updateMessageStatusById(String channelMessageId, Integer messageStatus,Class<? extends ChannelMessage> channelMessageClass) {
		Query query = new Query(Criteria.where("_id").is(channelMessageId));
		Update update = new Update();
		update.inc("retry_count", CommonConstants.ONE);
		update.inc("version", CommonConstants.ONE);
		update.set("update_time", LocalDateTime.now());
		update.set("update_by", OperateAuthUtil.getAdministrator());
		update.set("status",messageStatus);
		UpdateResult updateResult = mongoTemplate.updateFirst(query, update, channelMessageClass);
		return updateResult.wasAcknowledged();
	}

	@Override
	public List<? extends ChannelMessage> findByUniqueKey(String uniqueKey, Class<? extends ChannelMessage> channelMessageClass) {
		Criteria criteria = new Criteria();
		criteria.and("del_flag").is(CommonConstants.ZERO);
		criteria.and("unique_key").is(uniqueKey);
		return mongoTemplate.find(Query.query(criteria), channelMessageClass);
	}

	@Override
	public boolean existsByUniqueKey(String uniqueKey, Class<? extends ChannelMessage> channelMessageClass) {
		Criteria criteria = new Criteria();
		criteria.and("del_flag").is(CommonConstants.ZERO);
		criteria.and("unique_key").is(uniqueKey);
		return mongoTemplate.exists(Query.query(criteria), channelMessageClass);
	}

	@Override
	public ChannelMessage save(ChannelMessage channelMessage) {
		return mongoTemplate.save(channelMessage);
	}

	@Override
	public Collection<ChannelMessage> insertAll(List<ChannelMessage> channelMessages) {
		return mongoTemplate.insertAll(channelMessages);
	}

	@Override
	public ChannelMessage getById(String channelMessageId, Class<? extends ChannelMessage> channelMessageClass) {
		return mongoTemplate.findById(channelMessageId,channelMessageClass);
	}

	@Override
	public Page<ChannelMessage> page(Page<Object> pageParam, Query query) {
		String tableNameSuffix = DynamicTableNameHelper.getRequestData(SupplyMapperConstant.CHANNEL_MESSAGE_TABLE_NAME);
		Class<? extends ChannelMessage> clazz = Objects.equals(tableNameSuffix,SupplyMapperConstant.CHANNEL_MESSAGE_ORDER_SUFFIX) ? ChannelMessageOrder.class : ChannelMessageProduct.class;
		// 12. 总记录数
		long total = mongoTemplate.count(query, clazz);
		// 8. 查询返回指定字段 (自定义列表)
		//query.fields().include()
		// 10. 分页、排序
		int pageNo = Long.valueOf(pageParam.getCurrent() - 1).intValue();
		int size = Long.valueOf(pageParam.getSize()).intValue();
		query.with(PageRequest.of(pageNo, size, Sort.by(Sort.Order.desc("create_time"))));
		List<? extends ChannelMessage> channelMessages = mongoTemplate.find(query, clazz);
		Page<ChannelMessage> page = Page.of(pageNo, size, total);
		page.setRecords(channelMessages.stream()
				.filter(channelMessage -> channelMessage instanceof ChannelMessage)
				.map(channelMessage -> (ChannelMessage)channelMessage)
				.collect(Collectors.toList()));
		return page;
	}

	@Override
	public Boolean updateChannelMessageStatus(Query query, Update update) {
		String tableNameSuffix = DynamicTableNameHelper.getRequestData(SupplyMapperConstant.CHANNEL_MESSAGE_TABLE_NAME);
		Class<? extends ChannelMessage> clazz = Objects.equals(tableNameSuffix,SupplyMapperConstant.CHANNEL_MESSAGE_ORDER_SUFFIX) ? ChannelMessageOrder.class : ChannelMessageProduct.class;
		UpdateResult updateResult = mongoTemplate.updateFirst(query, update, clazz);
		return updateResult.wasAcknowledged();
	}

	@Override
	public List<ChannelMessageOrder> channelMessageOrderList(int skipCount, int limit, List<Integer> messageStatusList, Integer lteRetryCount) {
		Criteria criteria = new Criteria();
		criteria.and("del_flag").is(CommonConstants.ZERO);
		if(CollectionUtils.isNotEmpty(messageStatusList)) {
			criteria.and("status").in(messageStatusList);
		}
		if(Objects.nonNull(lteRetryCount)) {
			criteria.and("retry_count").lte(lteRetryCount);
		}
		return mongoTemplate.find(Query.query(criteria).with(Sort.by(Sort.Order.asc("create_time"))).skip(skipCount).limit(limit), ChannelMessageOrder.class);
	}

	@Override
	public void resetRetryCount(String channelMessageId, Class<? extends ChannelMessage> clazz) {
		Query query = new Query(Criteria.where("_id").is(channelMessageId));
		Update fieldName = Update.update("retry_count", CommonConstants.ZERO);;
		mongoTemplate.updateMulti(query, fieldName, clazz);
	}
}
